﻿using SL651Center2.x.Enums;
using SL651Center2.x.Messages;
using System.Text;

namespace SL651Center2.x.Send
{
    public class CreateSend
    {
        /// <summary>
        /// 创建报头
        /// </summary>
        /// <param name="frameCode">帧编码格式</param>
        /// <param name="centerAddr">中心站地址</param>
        /// <param name="telemetryAddr">遥测站地址</param>
        /// <param name="pwd">密码</param>
        /// <param name="functionCode">功能码</param>
        /// <returns>报文字节数组</returns>
        public static MessageFrame BuildHead(FrameCode frameCode, string centerAddr, string telemetryAddr, string pwd, FunctionCode functionCode)
        {
            MessageFrame header = new MessageFrame();

            //判断报文格式
            if (frameCode == FrameCode.ASCII)
            {
                //帧起始符
                header.FrameCoding = MessageFrame.ASCII;
                //遥测站地址
                header.TelemetryAddress = Encoding.ASCII.GetBytes(telemetryAddr);
                //中心站地址
                header.CentralAddress = Encoding.ASCII.GetBytes(centerAddr);
                //密码
                header.PassWord = Encoding.ASCII.GetBytes(pwd);
                //功能码
                header.FunctionCode = functionCode;
                //报文起始符
                header.StartMark = StartMarks.STX;
                //报文结束符
                header.EndMark = EndMarks.ENQ;
                return header;
            }
            else
            {
                //帧起始符
                header.FrameCoding = MessageFrame.HEX_BCD;
                //遥测站地址
                header.TelemetryAddress = Helper.HEXStrToByte(telemetryAddr);
                //中心站地址
                header.CentralAddress = Helper.HEXStrToByte(centerAddr);
                //密码
                header.PassWord = Helper.HEXStrToByte(pwd);
                //功能码
                header.FunctionCode = functionCode;
                //报文起始符
                header.StartMark = StartMarks.STX;
                //报文结束符
                header.EndMark = EndMarks.ENQ;
                return header;
            }


        }

        /// <summary>
        /// 创建报头
        /// </summary>
        /// <param name="telemetryInfo">遥测站信息</param>
        /// <param name="functionCode">功能码</param>
        /// <returns>报文字节数组</returns>
        public static MessageFrame BuildHead(TelemetryInfo telemetryInfo, FunctionCode functionCode)
        {
            MessageFrame header = new MessageFrame();

            //判断报文格式并添加对应的帧起始符
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                header.FrameCoding = MessageFrame.ASCII;
                
            }
            else
            {
                header.FrameCoding = MessageFrame.HEX_BCD;
            }
            header.FrameCode = telemetryInfo.FrameCode;
            //遥测站地址
            header.TelemetryAddress = telemetryInfo.TelemetryAddress;
            //中心站地址
            header.CentralAddress = telemetryInfo.CentralAddress;
            //密码
            header.PassWord = telemetryInfo.PassWord;
            //功能码
            header.FunctionCode = functionCode;
            //报文起始符
            header.StartMark = StartMarks.STX;
            //报文结束符
            header.EndMark = EndMarks.ENQ;
            return header;
        }

        /// <summary>
        /// 创建报文
        /// </summary>
        /// <param name="head">报头</param>
        /// <param name="body">正文字节数组</param>
        /// <returns>报文字节数组</returns>
        public static byte[] BuildMessage(MessageFrame head, byte[] body)
        {
            List<byte> bytes = new List<byte>();

            //帧起始符
            bytes.AddRange(head.FrameCoding);
            //遥测站地址
            bytes.AddRange(head.TelemetryAddress);
            //中心站地址
            bytes.AddRange(head.CentralAddress);
            //密码
            bytes.AddRange(head.PassWord);
            //功能码
            byte code = (byte)head.FunctionCode;
            if (head.FrameCoding.Length == 1)
            {
                var fh = Helper.ToHEXString(code);
                var ah = Encoding.ASCII.GetBytes(fh);
                bytes.AddRange(ah);
            }
            else
            {
                bytes.Add(code);
            }

            //获取正文长度
            var len = body.Length;

            //上下行表示和报文长度
            string lenb = Convert.ToString(len, 2).PadLeft(12, '0');
            string ln = $"1000{lenb}";
            var hexlen = string.Format("{0:X2}", Convert.ToInt16(ln, 2));
            //判断帧格式，进行对应的转码
            if (head.FrameCoding.Length == 1)
            {
                var bl = Encoding.ASCII.GetBytes(hexlen);
                bytes.AddRange(bl);
            }
            else
            {
                var bl = Helper.HEXStrToByte(hexlen);
                bytes.AddRange(bl);
            }

            //报文起始符
            bytes.Add((byte)head.StartMark);

            if (head.Package.Any())
            {
                bytes.AddRange(head.Package);
            }

            //正文
            bytes.AddRange(body);

            //报文结束符
            bytes.Add((byte)head.EndMark);

            //校验码
            var crc = Helper.Crc16(bytes.ToArray());
            //判断帧格式，进行对应的转码
            if (head.FrameCoding.Length == 1)
            {
                var ch = Helper.ToHEXString(crc);
                var cb = Encoding.ASCII.GetBytes(ch);
                bytes.AddRange(cb);
            }
            else
            {
                bytes.AddRange(crc);
            }

            return bytes.ToArray();
        }

        /// <summary>
        /// 创建多包发送的报文
        /// </summary>
        /// <param name="head">报头</param>
        /// <param name="body">正文字节数组</param>
        /// <param name="index">包序列号</param>
        /// <param name="count">包总数</param>
        /// <returns>报文字节数组z</returns>
        public static byte[] BulidMessage(MessageFrame head, byte[] body, int index, int count)
        {
            List<byte> bytes = new List<byte>();

            //帧起始符
            bytes.AddRange(head.FrameCoding);
            //遥测站地址
            bytes.AddRange(head.TelemetryAddress);
            //中心站地址
            bytes.AddRange(head.CentralAddress);
            //密码
            bytes.AddRange(head.PassWord);
            //功能码
            byte code = (byte)head.FunctionCode;
            if (head.FrameCoding.Length == 1)
            {
                var fh = Helper.ToHEXString(code);
                var ah = Encoding.ASCII.GetBytes(fh);
                bytes.AddRange(ah);
            }
            else
            {
                bytes.Add(code);
            }

            //正文长度
            var len = body.Length;

            //上下行标识及长度
            var lenb = Convert.ToString(len, 16).PadLeft(8, '0');
            var hexlen = $"8{lenb}";
            //var hexlen = string.Format("{0:X2}", Convert.ToUInt16(ln, 2));
            //判断帧格式
            if (head.FrameCoding.Length == 1)
            {
                var bl = Encoding.ASCII.GetBytes(hexlen);
                bytes.AddRange(bl);
            }
            else
            {
                var bl = Helper.HEXStrToByte(hexlen);
                bytes.AddRange(bl);
            }

            //报文起始符
            bytes.Add((byte)head.StartMark);

            //包总数及序列号
            var conb = Convert.ToString(count, 16).PadLeft(3, '0');
            var inxb = Convert.ToString(index, 16).PadLeft(3, '0');
            var hexpack = $"{conb}{index}";
            if (head.FrameCoding.Length == 1)
            {
                var packb = Encoding.ASCII.GetBytes(hexpack);
                bytes.AddRange(packb);
            }
            else
            {
                var packb = Helper.HEXStrToByte(hexpack);
                bytes.AddRange(packb);
            }

            //正文
            bytes.AddRange(body);

            //报文结束符
            bytes.Add((byte)head.StartMark);

            //校验码
            var crc = Helper.Crc16(bytes.ToArray());
            if (head.FrameCoding.Length == 1)
            {
                var ch = Helper.ToHEXString(crc);
                var cb = Encoding.ASCII.GetBytes(ch);
                bytes.AddRange(cb);
            }
            else
            {
                bytes.AddRange(crc);
            }

            return bytes.ToArray();
        }

        /// <summary>
        /// 查询遥测站图片的报文
        /// </summary>
        /// <param name="telemetryInfo">遥测站信息</param>
        /// <returns>报文字节数组</returns>
        public static byte[] QueryImgData(TelemetryInfo telemetryInfo)
        {
            //获取报头
            var head = BuildHead(telemetryInfo, FunctionCode.FC_36);
            //获取报文字节数组
            var bytes = BuildResponse.CreatResponse(head, 0, EndMarks.ENQ);
            return bytes;
        }

        /// <summary>
        /// 查询遥测站实时数据
        /// </summary>
        /// <param name="telemetryInfo">遥测站信息</param>
        /// <returns>报文字节数组</returns>
        public static byte[] QueryRealTimeData(TelemetryInfo telemetryInfo)
        {
            //获取报头
            var head = BuildHead(telemetryInfo, FunctionCode.FC_37);
            //获取报文字节数组
            var bytes = BuildResponse.CreatResponse(head, 0, EndMarks.ENQ);
            return bytes;
        }

        /// <summary>
        /// 查询遥测站时段数据
        /// </summary>
        /// <param name="telemetryInfo">遥测站信息</param>
        /// <param name="startTime">开始时间</param>
        /// <param name="endTime">结束时间</param>
        /// <param name="drn">时间步长码.格式:000000</param>
        /// <param name="elementCode">要素</param>
        /// <returns>报文字节数组</returns>
        public static byte[] QueryTimePeriodData(TelemetryInfo telemetryInfo, DateTime startTime, DateTime endTime, string drn, params ElementCode[] elementCode)
        {
            var head = BuildHead(telemetryInfo, FunctionCode.FC_38);

            List<byte> bytes = new List<byte>();
            //帧起始符
            bytes.AddRange(head.FrameCoding);
            //遥测站地址
            bytes.AddRange(head.TelemetryAddress);
            //中心站地址
            bytes.AddRange(head.CentralAddress);
            //密码
            bytes.AddRange(head.PassWord);
            //功能码
            byte code = (byte)head.FunctionCode;
            if (head.FrameCoding.Length == 1)
            {
                var fh = Helper.ToHEXString(code);
                var ah = Encoding.ASCII.GetBytes(fh);
                bytes.AddRange(ah);
            }
            else
            {
                bytes.Add(code);
            }

            //获取报文正文
            var body = MessageBody.BuildTimePeriodDataBody(telemetryInfo.FrameCode, startTime, endTime, drn, elementCode);
            var len = body.Length;

            //上下行表示和报文长度
            string lenb = Convert.ToString(len, 2).PadLeft(12, '0');
            string ln = $"1000{lenb}";
            var hexlen = string.Format("{0:X2}", Convert.ToInt16(ln, 2));
            //判断帧格式，进行对应的转码
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                var bl = Encoding.ASCII.GetBytes(hexlen);
                bytes.AddRange(bl);
            }
            else
            {
                var bl = Helper.HEXStrToByte(hexlen);
                bytes.AddRange(bl);
            }

            //报文起始符
            bytes.Add((byte)head.StartMark);

            //正文
            bytes.AddRange(body);

            //报文结束符
            bytes.Add((byte)head.EndMark);

            //校验码
            var crc = Helper.Crc16(bytes.ToArray());
            //判断帧格式，进行对应的转码
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                var ch = Helper.ToHEXString(crc);
                var cb = Encoding.ASCII.GetBytes(ch);
                bytes.AddRange(cb);
            }
            else
            {
                bytes.AddRange(crc);
            }

            return bytes.ToArray();
        }

        /// <summary>
        /// 查询遥测站人工置数
        /// </summary>
        /// <param name="telemetryInfo">遥测站信息</param>
        /// <returns>报文字节数组</returns>
        public static byte[] QueryArtificialData(TelemetryInfo telemetryInfo)
        {
            //获取报头
            var head = BuildHead(telemetryInfo, FunctionCode.FC_39);
            //获取报文字节数组
            var bytes = BuildResponse.CreatResponse(head, 0, EndMarks.ENQ);
            return bytes;
        }

        /// <summary>
        /// 查询遥测站指定要素数据
        /// </summary>
        /// <param name="telemetryInfo">遥测站信息</param>
        /// <param name="elementCodes">要查询的要素</param>
        /// <returns>报文字节数组</returns>
        public static byte[] QueryElementData(TelemetryInfo telemetryInfo, params ElementCode[] elementCodes)
        {
            //获取报头
            var head = BuildHead(telemetryInfo, FunctionCode.FC_3A);

            List<byte> bytes = new List<byte>();

            //帧起始符
            bytes.AddRange(head.FrameCoding);
            //遥测站地址
            bytes.AddRange(head.TelemetryAddress);
            //中心站地址
            bytes.AddRange(head.CentralAddress);
            //密码
            bytes.AddRange(head.PassWord);
            //功能码
            byte code = (byte)head.FunctionCode;
            if (head.FrameCoding.Length == 1)
            {
                var fh = Helper.ToHEXString(code);
                var ah = Encoding.ASCII.GetBytes(fh);
                bytes.AddRange(ah);
            }
            else
            {
                bytes.Add(code);
            }

            //获取正文
            var body = MessageBody.BuildElementDataBody(telemetryInfo.FrameCode, elementCodes);
            var len = body.Length;

            //上下行表示和报文长度
            string lenb = Convert.ToString(len, 2).PadLeft(12, '0');
            string ln = $"1000{lenb}";
            var hexlen = string.Format("{0:X2}", Convert.ToInt16(ln, 2));
            //判断帧格式，进行对应的转码
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                var bl = Encoding.ASCII.GetBytes(hexlen);
                bytes.AddRange(bl);
            }
            else
            {
                var bl = Helper.HEXStrToByte(hexlen);
                bytes.AddRange(bl);
            }

            //报文起始符
            bytes.Add((byte)head.StartMark);

            //正文
            bytes.AddRange(body);

            //报文结束符
            bytes.Add((byte)head.EndMark);

            //校验码
            var crc = Helper.Crc16(bytes.ToArray());
            //判断帧格式，进行对应的转码
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                var ch = Helper.ToHEXString(crc);
                var cb = Encoding.ASCII.GetBytes(ch);
                bytes.AddRange(cb);
            }
            else
            {
                bytes.AddRange(crc);
            }

            return bytes.ToArray();

        }

        /// <summary>
        /// 修改遥测站基本配置
        /// </summary>
        /// <param name="telemetryInfo">遥测站信息</param>
        /// <param name="datas">基本配置参数</param>
        /// <returns>报文字节数组</returns>
        public static byte[] SetBasicConfig(TelemetryInfo telemetryInfo, BasicConfigData[] datas)
        {
            var head = BuildHead(telemetryInfo, FunctionCode.FC_40);

            List<byte> bytes = new List<byte>();

            //帧起始符
            bytes.AddRange(head.FrameCoding);
            //遥测站地址
            bytes.AddRange(head.TelemetryAddress);
            //中心站地址
            bytes.AddRange(head.CentralAddress);
            //密码
            bytes.AddRange(head.PassWord);
            //功能码
            byte code = (byte)head.FunctionCode;
            //根据不同的帧格式写入功能码
            if (head.FrameCoding.Length == 1)
            {
                var fh = Helper.ToHEXString(code);
                var ah = Encoding.ASCII.GetBytes(fh);
                bytes.AddRange(ah);
            }
            else
            {
                bytes.Add(code);
            }

            //正文
            var body = MessageBody.BuildSetBasicConfigBody(telemetryInfo.FrameCode, datas);
            var len = body.Length;

            //上下行标识及长度
            var lenb = Convert.ToString(len, 2).PadLeft(12, '0');
            var ln = $"1000{lenb}";
            var hexlen = string.Format("{0:X2}", Convert.ToUInt16(ln, 2));
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                var bl = Encoding.ASCII.GetBytes(hexlen);
                bytes.AddRange(bl);
            }
            else
            {
                var bl = Helper.HEXStrToByte(hexlen);
                bytes.AddRange(bl);
            }
            //报文起始符
            bytes.Add((byte)head.StartMark);
            //正文
            bytes.AddRange(body);
            //报文结束符
            bytes.Add((byte)head.EndMark);

            //校验码
            var crc = Helper.Crc16(bytes.ToArray());
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                var ch = Helper.ToHEXString(crc);
                var cb = Encoding.ASCII.GetBytes(ch);
                bytes.AddRange(cb);
            }
            else
            {
                bytes.AddRange(crc);
            }

            return bytes.ToArray();
        }

        /// <summary>
        /// 查询遥测站基本配置表
        /// </summary>
        /// <param name="telemetryInfo">遥测站信息</param>
        /// <param name="basicConfigCodes">要查询的基本配置</param>
        /// <returns>报文字节数组</returns>
        public static byte[] QueryBasicConfig(TelemetryInfo telemetryInfo, params BasicConfigCode[] basicConfigCodes)
        {
            var head = BuildHead(telemetryInfo, FunctionCode.FC_41);

            List<byte> bytes = new List<byte>();

            //帧起始符
            bytes.AddRange(head.FrameCoding);
            //遥测站地址
            bytes.AddRange(head.TelemetryAddress);
            //中心站地址
            bytes.AddRange(head.CentralAddress);
            //密码
            bytes.AddRange(head.PassWord);
            //功能码
            byte code = (byte)head.FunctionCode;
            if (head.FrameCoding.Length == 1)
            {
                var fh = Helper.ToHEXString(code);
                var ah = Encoding.ASCII.GetBytes(fh);
                bytes.AddRange(ah);
            }
            else
            {
                bytes.Add(code);
            }

            var body = MessageBody.BuildQueryBasicConfigBody(telemetryInfo.FrameCode, basicConfigCodes);
            var len = body.Length;

            //上下行标识及长度
            string lenb = Convert.ToString(len, 2).PadLeft(12, '0');
            string ln = $"1000{lenb}";
            var hexlen = string.Format("{0:X2}", Convert.ToInt16(ln, 2));
            //判断帧格式，进行对应的转码
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                var bl = Encoding.ASCII.GetBytes(hexlen);
                bytes.AddRange(bl);
            }
            else
            {
                var bl = Helper.HEXStrToByte(hexlen);
                bytes.AddRange(bl);
            }
            //报文起始符
            bytes.Add((byte)head.StartMark);

            //正文
            bytes.AddRange(body);

            //报文结束符
            bytes.Add((byte)head.EndMark);

            //校验码
            var crc = Helper.Crc16(bytes.ToArray());
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                var ch = Helper.ToHEXString(crc);
                var cb = Encoding.ASCII.GetBytes(ch);
                bytes.AddRange(cb);
            }
            else
            {
                bytes.AddRange(crc);
            }

            return bytes.ToArray();
        }

        /// <summary>
        /// 修改遥测站运行配置
        /// </summary>
        /// <param name="telemetryInfo">遥测站信息</param>
        /// <param name="datas">运行配置参数</param>
        /// <returns>报文的字节数组</returns>
        public static byte[] SetRunConfig(TelemetryInfo telemetryInfo, RunConfigData[] datas)
        {
            var head = BuildHead(telemetryInfo, FunctionCode.FC_42);

            List<byte> bytes = new List<byte>();

            //帧起始符
            bytes.AddRange(head.FrameCoding);
            //遥测站地址
            bytes.AddRange(head.TelemetryAddress);
            //中心站地址
            bytes.AddRange(head.CentralAddress);
            //密码
            bytes.AddRange(head.PassWord);
            //功能码
            byte code = (byte)head.FunctionCode;
            //根据不同的帧格式写入功能码
            if (head.FrameCoding.Length == 1)
            {
                var fh = Helper.ToHEXString(code);
                var ah = Encoding.ASCII.GetBytes(fh);
                bytes.AddRange(ah);
            }
            else
            {
                bytes.Add(code);
            }

            //正文
            var body = MessageBody.BuildSetRunConfigBody(telemetryInfo.FrameCode, datas);
            var len = body.Length;

            //上下行标识及长度
            var lenb = Convert.ToString(len, 2).PadLeft(12, '0');
            var ln = $"1000{lenb}";
            var hexlen = string.Format("{0:X2}", Convert.ToUInt16(ln, 2));
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                var bl = Encoding.ASCII.GetBytes(hexlen);
                bytes.AddRange(bl);
            }
            else
            {
                var bl = Helper.HEXStrToByte(hexlen);
                bytes.AddRange(bl);
            }
            //报文起始符
            bytes.Add((byte)head.StartMark);
            //正文
            bytes.AddRange(body);
            //报文结束符
            bytes.Add((byte)head.EndMark);

            //校验码
            var crc = Helper.Crc16(bytes.ToArray());
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                var ch = Helper.ToHEXString(crc);
                var cb = Encoding.ASCII.GetBytes(ch);
                bytes.AddRange(cb);
            }
            else
            {
                bytes.AddRange(crc);
            }

            return bytes.ToArray();

        }

        /// <summary>
        /// 查询遥测站运行配置表
        /// </summary>
        /// <param name="telemetryInfo">遥测站信息</param>
        /// <param name="runConfigs">要查询的运行配置</param>
        /// <returns>报文的字节数组</returns>
        public static byte[] QueryRunConfig(TelemetryInfo telemetryInfo, params RunConfigCode[] runConfigs)
        {
            var head = BuildHead(telemetryInfo, FunctionCode.FC_43);

            List<byte> bytes = new List<byte>();

            //帧起始符
            bytes.AddRange(head.FrameCoding);
            //遥测站地址
            bytes.AddRange(head.TelemetryAddress);
            //中心站地址
            bytes.AddRange(head.CentralAddress);
            //密码
            bytes.AddRange(head.PassWord);
            //功能码
            byte code = (byte)head.FunctionCode;
            if (head.FrameCoding.Length == 1)
            {
                var fh = Helper.ToHEXString(code);
                var ah = Encoding.ASCII.GetBytes(fh);
                bytes.AddRange(ah);
            }
            else
            {
                bytes.Add(code);
            }

            //正文
            var body = MessageBody.BuildQueryRunConfigBody(telemetryInfo.FrameCode, runConfigs);
            var len = body.Length;

            //上下行标识及长度
            var lenb = Convert.ToString(len, 2).PadLeft(12, '0');
            var ln = $"1000{lenb}";
            var hexlen = string.Format("{0:X2}", Convert.ToUInt16(ln, 2));
            //判断帧格式
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                var bl = Encoding.ASCII.GetBytes(hexlen);
                bytes.AddRange(bl);
            }
            else
            {
                var bl = Helper.HEXStrToByte(hexlen);
                bytes.AddRange(bl);
            }
            //报文起始符
            bytes.Add((byte)head.StartMark);

            //正文
            bytes.AddRange(body);

            //报文结束符
            bytes.Add((byte)head.EndMark);

            //校验码
            var crc = Helper.Crc16(bytes.ToArray());
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                var ch = Helper.ToHEXString(crc);
                var cb = Encoding.ASCII.GetBytes(ch);
                bytes.AddRange(cb);
            }
            else
            {
                bytes.AddRange(crc);
            }

            return bytes.ToArray();
        }

        /// <summary>
        /// 查询遥测站水泵电机实时数据
        /// </summary>
        /// <param name="telemetryInfo">遥测站信息</param>
        /// <returns>报文的字节数组</returns>
        public static byte[] QueryWaterPumpMotorData(TelemetryInfo telemetryInfo)
        {
            //获取报头
            var head = BuildHead(telemetryInfo, FunctionCode.FC_44);
            //获取报文字节数组
            var bytes = BuildResponse.CreatResponse(head, 0, EndMarks.ENQ);
            return bytes;
        }

        /// <summary>
        /// 查询遥测站软件版本信息
        /// </summary>
        /// <param name="telemetryInfo">遥测站信息</param>
        /// <returns>报文字节数组</returns>
        public static byte[] QuerySoftwareVer(TelemetryInfo telemetryInfo)
        {
            //获取报头
            var head = BuildHead(telemetryInfo, FunctionCode.FC_45);
            //获取正文
            var bytes = BuildResponse.CreatResponse(head, 0, EndMarks.ENQ);
            return bytes;
        }

        /// <summary>
        /// 查询遥测站状态和报警信息
        /// </summary>
        /// <param name="telemetryInfo">遥测站信息</param>
        /// <returns>报文字节数组</returns>
        public static byte[] QueryState(TelemetryInfo telemetryInfo)
        {
            //获取报头
            var head = BuildHead(telemetryInfo, FunctionCode.FC_46);
            //获取正文
            var bytes = BuildResponse.CreatResponse(head, 0, EndMarks.ENQ);
            return bytes;
        }

        /// <summary>
        /// 初始化遥测站固态存储数据
        /// </summary>
        /// <param name="telemetryInfo">遥测站信息</param>
        /// <returns>报文字节数组</returns>
        public static byte[] InitializeData(TelemetryInfo telemetryInfo)
        {
            //获取报头
            var head = BuildHead(telemetryInfo, FunctionCode.FC_47);

            List<byte> data = new List<byte>();

            //帧起始符
            data.AddRange(head.FrameCoding);
            //遥测站地址
            data.AddRange(head.TelemetryAddress);
            //中心站地址
            data.AddRange(head.CentralAddress);
            //密码
            data.AddRange(head.PassWord);
            //功能码
            byte code = (byte)head.FunctionCode;
            if (head.FrameCoding.Length == 1)
            {
                var fh = Helper.ToHEXString(code);
                var ah = Encoding.ASCII.GetBytes(fh);
                data.AddRange(ah);
            }
            else
            {
                data.Add(code);
            }

            //正文
            var body = MessageBody.BuildInitializeData(telemetryInfo.FrameCode);
            var len = body.Length;

            //上下行标识及长度
            var lenb = Convert.ToString(len, 2).PadLeft(12, '0');
            var ln = $"1000{lenb}";
            var hexlen = string.Format("{0:X2}", Convert.ToInt16(ln, 2));
            //判断帧格式
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                var bl = Encoding.ASCII.GetBytes(hexlen);
                data.AddRange(bl);
            }
            else
            {
                var bl = Helper.HEXStrToByte(hexlen);
                data.AddRange(bl);
            }
            //报文起始符
            data.Add((byte)head.StartMark);

            //正文
            data.AddRange(body);

            //报文结束符
            data.Add((byte)head.EndMark);

            //校验码 
            var crc = Helper.Crc16(data.ToArray());
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                var ch = Helper.ToHEXString(crc);
                var cb = Encoding.ASCII.GetBytes(ch);
                data.AddRange(cb);
            }
            else
            {
                data.AddRange(crc);
            }

            return data.ToArray();
        }

        /// <summary>
        /// 恢复遥测站出厂设置
        /// </summary>
        /// <param name="telemetryInfo">遥测站信息</param>
        /// <returns>报文字节数组</returns>
        public static byte[] FactoryReset(TelemetryInfo telemetryInfo)
        {
            var head = BuildHead(telemetryInfo, FunctionCode.FC_48);

            List<byte> data = new List<byte>();
            //帧起始符
            data.AddRange(head.FrameCoding);
            //遥测站地址
            data.AddRange(head.TelemetryAddress);
            //中心站地址
            data.AddRange(head.CentralAddress);
            //密码
            data.AddRange(head.PassWord);
            //功能码
            byte code = (byte)head.FunctionCode;
            if (head.FrameCoding.Length == 1)
            {
                var fh = Helper.ToHEXString(code);
                var ah = Encoding.ASCII.GetBytes(fh);
                data.AddRange(ah);
            }
            else
            {
                data.Add(code);
            }

            //正文
            var body = MessageBody.BuildFactoryReset(telemetryInfo.FrameCode);
            var len = body.Length;

            //上下行标识及长度
            var lenb = Convert.ToString(len, 2).PadLeft(12, '0');
            var ln = $"1000{lenb}";
            var hexlen = string.Format("{0:X2}", Convert.ToUInt16(ln, 2));
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                var bl = Encoding.ASCII.GetBytes(hexlen);
                data.AddRange(bl);
            }
            else
            {
                var bl = Helper.HEXStrToByte(hexlen);
                data.AddRange(bl);
            }
            //报文起始符
            data.Add((byte)head.StartMark);
            //正文
            data.AddRange(body);
            //报文结束符
            data.Add((byte)head.EndMark);
            //校验码
            var crc = Helper.Crc16(data.ToArray());
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                var ch = Helper.ToHEXString(crc);
                var cb = Encoding.ASCII.GetBytes(ch);
                data.AddRange(cb);
            }
            else
            {
                data.AddRange(crc);
            }

            return data.ToArray();
        }

        /// <summary>
        /// 修改遥测站密码
        /// </summary>
        /// <param name="telemetryInfo">遥测站信息</param>
        /// <param name="oldPwd">旧密码(十六进制字符串)</param>
        /// <param name="newPwd">新密码(十六进制字符串)</param>
        /// <returns>报文字节数组</returns>
        public static byte[] ChangePassWord(TelemetryInfo telemetryInfo, string oldPwd, string newPwd)
        {
            var head = BuildHead(telemetryInfo, FunctionCode.FC_49);

            List<byte> data = new List<byte>();

            //帧起始符
            data.AddRange(head.FrameCoding);
            //遥测站地址
            data.AddRange(head.TelemetryAddress);
            //中心站地址
            data.AddRange(head.CentralAddress);
            //密码
            data.AddRange(head.PassWord);
            //功能码
            byte code = (byte)head.FunctionCode;
            if (head.FrameCoding.Length == 1)
            {
                var fh = Helper.ToHEXString(code);
                var ah = Encoding.ASCII.GetBytes(fh);
                data.AddRange(ah);
            }
            else
            {
                data.Add(code);
            }

            //正文
            var body = MessageBody.BuildChangePassWord(telemetryInfo.FrameCode, oldPwd, newPwd);
            var len = body.Length;

            //上下行标识及正文长度
            var lenb = Convert.ToString(len, 2).PadLeft(12, '0');
            var ln = $"1000{lenb}";
            var hexlen = string.Format("{0:X2}", Convert.ToUInt16(ln, 2));
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                var bl = Encoding.ASCII.GetBytes(hexlen);
                data.AddRange(bl);
            }
            else
            {
                var bl = Helper.HEXStrToByte(hexlen);
                data.AddRange(bl);
            }
            //报文起始符
            data.Add((byte)head.StartMark);
            //正文
            data.AddRange(body);
            //报文结束符
            data.Add((byte)head.EndMark);

            //校验码
            var crc = Helper.Crc16(data.ToArray());
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                var ch = Helper.ToHEXString(crc);
                var cb = Encoding.ASCII.GetBytes(ch);
                data.AddRange(cb);
            }
            else
            {
                data.AddRange(crc);
            }

            return data.ToArray();

        }

        /// <summary>
        /// 设置遥测站时钟
        /// </summary>
        /// <param name="telemetryInfo">遥测站信息</param>
        /// <returns>报文的字节数组</returns>
        public static byte[] SetClock(TelemetryInfo telemetryInfo)
        {
            var head = BuildHead(telemetryInfo, FunctionCode.FC_4A);
            var body = BuildResponse.CreatResponse(head, 0, head.EndMark);
            return body;
        }

        /// <summary>
        /// 设置遥测站IC卡状态
        /// </summary>
        /// <param name="telemetryInfo">遥测站信息</param>
        /// <param name="type">IC卡状态。true:有效。false:关闭</param>
        /// <returns>报文的字节数组</returns>
        public static byte[] SetIcCardState(TelemetryInfo telemetryInfo, bool type)
        {
            var head = BuildHead(telemetryInfo, FunctionCode.FC_4B);

            List<byte> data = new List<byte>();
            //帧起始符
            data.AddRange(head.FrameCoding);
            //遥测站地址
            data.AddRange(head.TelemetryAddress);
            //中心站地址
            data.AddRange(head.CentralAddress);
            //密码
            data.AddRange(head.PassWord);
            //功能码
            byte code = (byte)head.FunctionCode;
            if (head.FrameCoding.Length == 1)
            {
                var fh = Helper.ToHEXString(code);
                var ah = Encoding.ASCII.GetBytes(fh);
                data.AddRange(ah);
            }
            else
            {
                data.Add(code);
            }

            //正文
            var body = MessageBody.BuildSetIcCardState(telemetryInfo.FrameCode, type);
            var len = body.Length;

            //上下行标识及长度
            var lenb = Convert.ToString(len, 2).PadLeft(12, '0');
            var ln = $"1000{lenb}";
            var hexlen = string.Format("{0:X2}", Convert.ToUInt16(ln, 2));
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                var bl = Encoding.ASCII.GetBytes(hexlen);
                data.AddRange(bl);
            }
            else
            {
                var bl = Helper.HEXStrToByte(hexlen);
                data.AddRange(bl);
            }
            //报文起始符
            data.Add((byte)head.StartMark);

            //正文
            data.AddRange(body);

            //报文结束符
            data.Add((byte)head.EndMark);

            //校验码
            var crc = Helper.Crc16(data.ToArray());
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                var ch = Helper.ToHEXString(crc);
                var cb = Encoding.ASCII.GetBytes(ch);
                data.AddRange(cb);
            }
            else
            {
                data.AddRange(crc);
            }

            return data.ToArray();
        }

        /// <summary>
        /// 控制水泵开关命令
        /// </summary>
        /// <param name="telemetryInfo">遥测站信息</param>
        /// <param name="types">水泵开关状态数组</param>
        /// <returns>报文的字节数组</returns>
        public static byte[] ControlPump(TelemetryInfo telemetryInfo, params bool[] types)
        {
            var head = BuildHead(telemetryInfo, FunctionCode.FC_4C);

            List<byte> data = new List<byte>();

            //帧起始符
            data.AddRange(head.FrameCoding);
            //遥测站地址
            data.AddRange(head.TelemetryAddress);
            //中心站地址
            data.AddRange(head.CentralAddress);
            //密码
            data.AddRange(head.PassWord);
            //功能码
            byte code = (byte)head.FunctionCode;
            if (head.FrameCoding.Length == 1)
            {
                var fh = Helper.ToHEXString(code);
                var ah = Encoding.ASCII.GetBytes(fh);
                data.AddRange(ah);
            }
            else
            {
                data.Add(code);
            }

            //正文
            var body = MessageBody.BuildControlPump(telemetryInfo.FrameCode, types);
            var len = body.Length;

            //上下行标识及长度
            var lenb = Convert.ToString(len, 2).PadLeft(12, '0');
            var ln = $"1000{lenb}";
            var hexlen = string.Format("{0:X2}", Convert.ToUInt16(ln, 2));
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                var bl = Encoding.ASCII.GetBytes(hexlen);
                data.AddRange(bl);
            }
            else
            {
                var bl = Helper.HEXStrToByte(hexlen);
                data.AddRange(bl);
            }
            //报文起始符
            data.Add((byte)head.StartMark);
            //正文
            data.AddRange(body);
            //报文结束符
            data.Add((byte)head.EndMark);

            //校验码
            var crc = Helper.Crc16(data.ToArray());
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                var ch = Helper.ToHEXString(crc);
                var cb = Encoding.ASCII.GetBytes(ch);
                data.AddRange(cb);
            }
            else
            {
                data.AddRange(crc);
            }

            return data.ToArray();

        }

        /// <summary>
        /// 控制阀门开关命令
        /// </summary>
        /// <param name="telemetryInfo">遥测站信息</param>
        /// <param name="types">阀门开关状态数组</param>
        /// <returns>报文的字节数组</returns>
        public static byte[] ControlValve(TelemetryInfo telemetryInfo, params bool[] types)
        {
            var head = BuildHead(telemetryInfo, FunctionCode.FC_4D);

            List<byte> data = new List<byte>();
            //帧起始符
            data.AddRange(head.FrameCoding);
            //遥测站地址
            data.AddRange(head.TelemetryAddress);
            //中心站地址
            data.AddRange(head.CentralAddress);
            //密码
            data.AddRange(head.PassWord);
            //功能码
            byte code = (byte)head.FunctionCode;
            if (head.FrameCoding.Length == 1)
            {
                var fh = Helper.ToHEXString(code);
                var ah = Encoding.ASCII.GetBytes(fh);
                data.AddRange(ah);
            }
            else
            {
                data.Add(code);
            }

            //正文
            var body = MessageBody.BuildControlPump(telemetryInfo.FrameCode, types);
            var len = body.Length;

            //上下行标识及长度
            var lenb = Convert.ToString(len, 2).PadLeft(12, '0');
            var ln = $"1000{lenb}";
            var hexlen = string.Format("{0:X2}", Convert.ToUInt16(ln, 2));
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                var bl = Encoding.ASCII.GetBytes(hexlen);
                data.AddRange(bl);
            }
            else
            {
                var bl = Helper.HEXStrToByte(hexlen);
                data.AddRange(bl);
            }
            //报文起始符
            data.Add((byte)head.StartMark);
            //正文
            data.AddRange(body);
            //报文结束符
            data.Add((byte)head.EndMark);

            //校验码
            var crc = Helper.Crc16(data.ToArray());
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                var ch = Helper.ToHEXString(crc);
                var cb = Encoding.ASCII.GetBytes(ch);
                data.AddRange(cb);
            }
            else
            {
                data.AddRange(crc);
            }

            return data.ToArray();

        }

        /// <summary>
        /// 控制闸门开关命令
        /// </summary>
        /// <param name="telemetryInfo">遥测站信息</param>
        /// <param name="types">闸门开关状态数组</param>
        /// <param name="open">闸门开度数据数组</param>
        /// <returns>报文的字节数组</returns>
        public static byte[] ControlGate(TelemetryInfo telemetryInfo, bool[] types, int[] open)
        {
            var head = BuildHead(telemetryInfo, FunctionCode.FC_4E);

            List<byte> data = new List<byte>();
            //帧起始符
            data.AddRange(head.FrameCoding);
            //遥测站地址
            data.AddRange(head.TelemetryAddress);
            //中心站地址
            data.AddRange(head.CentralAddress);
            //密码
            data.AddRange(head.PassWord);
            //功能码
            byte code = (byte)head.FunctionCode;
            if (head.FrameCoding.Length == 1)
            {
                var fh = Helper.ToHEXString(code);
                var ah = Encoding.ASCII.GetBytes(fh);
                data.AddRange(ah);
            }
            else
            {
                data.Add(code);
            }

            //正文
            var body = MessageBody.BuildControlGate(telemetryInfo.FrameCode, types, open);
            var len = body.Length;

            //上下行标识及长度
            var lenb = Convert.ToString(len, 2).PadLeft(12, '0');
            var ln = $"1000{lenb}";
            var hexlen = string.Format("{0:X2}", Convert.ToUInt16(ln, 2));
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                var bl = Encoding.ASCII.GetBytes(hexlen);
                data.AddRange(bl);
            }
            else
            {
                var bl = Helper.HEXStrToByte(hexlen);
                data.AddRange(bl);
            }

            //报文起始符
            data.Add((byte)head.StartMark);
            //正文
            data.AddRange(body);
            //报文结束符
            data.Add((byte)head.EndMark);

            //校验码
            var crc = Helper.Crc16(data.ToArray());
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                var ch = Helper.ToHEXString(crc);
                var cb = Encoding.ASCII.GetBytes(ch);
                data.AddRange(cb);
            }
            else
            {
                data.AddRange(crc);
            }

            return data.ToArray();
        }

        /// <summary>
        /// 控制水量定值命令
        /// </summary>
        /// <param name="telemetryInfo">遥测站信息</param>
        /// <param name="type">定值状态。true:定值投入.false:定值退出</param>
        /// <returns>报文的字节数组</returns>
        public static byte[] ControlWaterValue(TelemetryInfo telemetryInfo, bool type)
        {
            var head = BuildHead(telemetryInfo, FunctionCode.FC_4F);

            List<byte> data = new List<byte>();
            //帧起始符
            data.AddRange(head.FrameCoding);
            //遥测站地址
            data.AddRange(head.TelemetryAddress);
            //中心站地址
            data.AddRange(head.CentralAddress);
            //密码
            data.AddRange(head.PassWord);
            //功能码
            byte code = (byte)head.FunctionCode;
            if (head.FrameCoding.Length == 1)
            {
                var fh = Helper.ToHEXString(code);
                var ah = Encoding.ASCII.GetBytes(fh);
                data.AddRange(ah);
            }
            else
            {
                data.Add(code);
            }

            //正文
            var body = MessageBody.BuildControlWaterValue(telemetryInfo.FrameCode, type);
            var len = body.Length;

            //上下行标识及长度
            var lenb = Convert.ToString(len, 2).PadLeft(12, '0');
            var ln = $"1000{lenb}";
            var hexlen = string.Format("{0:X2}", Convert.ToUInt16(ln, 2));
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                var bl = Encoding.ASCII.GetBytes(hexlen);
                data.AddRange(bl);
            }
            else
            {
                var bl = Helper.HEXStrToByte(hexlen);
                data.AddRange(bl);
            }
            //报文起始符
            data.Add((byte)head.StartMark);
            //正文
            data.AddRange(body);
            //报文结束符
            data.Add((byte)head.EndMark);

            //校验码
            var crc = Helper.Crc16(data.ToArray());
            if (telemetryInfo.FrameCode == FrameCode.ASCII)
            {
                var ch = Helper.ToHEXString(crc);
                var cb = Encoding.ASCII.GetBytes(ch);
                data.AddRange(cb);
            }
            else
            {
                data.AddRange(crc);
            }

            return data.ToArray();
        }

        /// <summary>
        /// 查询遥测站事件记录
        /// </summary>
        /// <param name="telemetryInfo">遥测站信息</param>
        /// <returns>报文的字节数组</returns>
        public static byte[] QueryIncidentRecord(TelemetryInfo telemetryInfo)
        {
            var head = BuildHead(telemetryInfo, FunctionCode.FC_50);
            var body = BuildResponse.CreatResponse(head, 0, EndMarks.ENQ);
            return body;
        }

        /// <summary>
        /// 查询遥测站时钟
        /// </summary>
        /// <param name="telemetryInfo">遥测站信息</param>
        /// <returns>报文的字节数组</returns>
        public static byte[] QueryClock(TelemetryInfo telemetryInfo)
        {
            var head = BuildHead(telemetryInfo, FunctionCode.FC_51);
            var body = BuildResponse.CreatResponse(head, 0, EndMarks.ENQ);
            return body;
        }

    }
}
